﻿using Rud.Holmgren.TabulexLib.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Rud.Holmgren.Tabulex3000.Util
{
    class CommunicationManager
    {
        private static CommunicationManager instance;

        public static CommunicationManager Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = new CommunicationManager();
                }

                return instance;
            }
        }

        private IProgressManager progressMgr;

        public void Initialize(IProgressManager progressMgr)
        {
            this.progressMgr = progressMgr;
        }

        private bool isBusy = false;
        private Queue<ICommunicationTask> pendingTasks = new Queue<ICommunicationTask>();

        public void EnQueue(ICommunicationTask communicationTask)
        {
            lock (pendingTasks)
            {
                pendingTasks.Enqueue(communicationTask);

                if (!isBusy)
                {
                    RunNextTask();
                }
            }
        }

        private void RunNextTask()
        {
            lock (pendingTasks)
            {
                UpdateProgress();

                if (pendingTasks.Any())
                {
                    isBusy = true;

                    var task = pendingTasks.Dequeue();
                    task.Run().Fail(HandleTaskFail).Done(x => RunNextTask());
                }
                else
                {
                    isBusy = false;
                }
            }
        }

        private void UpdateProgress()
        {
            var caption = pendingTasks.Where(t => t.ShowCaption).Select(t => t.Caption).FirstOrDefault();
            progressMgr.SetState(caption != null, caption);
        }

        private void HandleTaskFail(PromiseFailArgs args)
        {
            lock (this)
            {
                // Show the error!!
                pendingTasks.Clear();
                isBusy = false;

                UpdateProgress();
            }
        }

        public void Clear()
        {
            pendingTasks.Clear();
        }
    }
}
